/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.artic.ogre.handler.nodes;

import com.artic.base.xml.XMLUtil;
import com.artic.ogre.handler.ISceneHandler;
import com.artic.ogre.handler.LightHandler;
import com.artic.ogre.model.Light;
import com.artic.ogre.model.Nodes;
import com.artic.ogre.model.Position;
import com.artic.ogre.model.Scale;
import com.artic.ogre.model.Scene;
import com.jme3.asset.AssetManager;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.scene.CameraNode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import java.util.List;

/**
 *
 * @author czarnik_a
 */
public class NodesHandler implements ISceneHandler {

    private ISceneHandler nextHandler;
    private static final String NODE_NAME = "Node";

    private AssetManager assetManager;
    private Scene scene;
    private Node node;

    public void setNext(ISceneHandler handler) {
        nextHandler = handler;
    }

    public void handleScene(Scene scene, Node node, AssetManager assetManager) {
        this.assetManager = assetManager;
        this.scene = scene;
        this.node = node;
        buildNodes();
        if(nextHandler != null) nextHandler.handleScene(scene, node, assetManager);
    }

    public void buildNodes() {
        Nodes nodes = scene.getNodes();
        for (com.artic.ogre.model.Node modelNode : nodes.getNode()) {
            Node jmeNode = new Node();
            if (!modelNode.getName().isEmpty()) {
                jmeNode.setName(modelNode.getName() + NODE_NAME);
            }
            generateNode(modelNode, jmeNode);
            node.attachChild(jmeNode);
        }
    }

    private void generateNode(com.artic.ogre.model.Node modelNode, Node jmeNode) {

        com.artic.ogre.model.Node nodeInNode = findInList(modelNode.getPositionOrOrientationOrQuaternion(), com.artic.ogre.model.Node.class);
        if (nodeInNode != null) {
            generateNode(modelNode, jmeNode);
        }

        com.artic.ogre.model.Camera camera = findInList(modelNode.getPositionOrOrientationOrQuaternion(), com.artic.ogre.model.Camera.class);
        if (camera != null) {
            CameraNode cameraNode = new CameraNode();
            if (camera.getPosition() != null) {
                cameraNode.setLocalTranslation(new Vector3f(XMLUtil.getFloatString(camera.getPosition().getX()), XMLUtil.getFloatString(camera.getPosition().getY()), XMLUtil.getFloatString(camera.getPosition().getZ())));
            }

            if (camera.getQuaternion() != null) {
                Quaternion jmeQuaternion = new Quaternion(XMLUtil.getFloatString(camera.getQuaternion().getX()), XMLUtil.getFloatString(camera.getQuaternion().getY()), XMLUtil.getFloatString(camera.getQuaternion().getZ()), XMLUtil.getFloatString(camera.getQuaternion().getW()));
                cameraNode.setLocalRotation(jmeQuaternion);
            }
            jmeNode.attachChild(new CameraNode());
        }

        com.artic.ogre.model.Entity entity = findInList(modelNode.getPositionOrOrientationOrQuaternion(), com.artic.ogre.model.Entity.class);
        if (entity != null) {
            Spatial spatial = (Spatial) assetManager.loadAsset(entity.getMeshFile());
            if (spatial != null) {
                jmeNode.attachChild(spatial);
            }else{
                System.out.println("[spatial not found]"+entity.getMeshFile());
            }
        }

        Light light = findInList(modelNode.getPositionOrOrientationOrQuaternion(), Light.class);

        if (light != null) {
            LightHandler lightLoader = new LightHandler();
            lightLoader.setAssetManager(assetManager);
            lightLoader.setNode(node);
            lightLoader.setScene(scene);
            lightLoader.addLight(light);
        }

        Position position = findInList(modelNode.getPositionOrOrientationOrQuaternion(), Position.class);
        if (position != null) {
            jmeNode.setLocalTranslation(XMLUtil.getFloatString(position.getX()), XMLUtil.getFloatString(position.getY()), XMLUtil.getFloatString(position.getZ()));
        }

        Scale scale = findInList(modelNode.getPositionOrOrientationOrQuaternion(), Scale.class);
        if (scale != null) {
            Vector3f vector3f = new Vector3f(XMLUtil.getFloatDouble(scale.getX()), XMLUtil.getFloatDouble(scale.getY()), XMLUtil.getFloatDouble(scale.getZ()));
            jmeNode.setLocalScale(vector3f);
        }

        com.artic.ogre.model.Quaternion dotSceneQuaternion = findInList(modelNode.getPositionOrOrientationOrQuaternion(), com.artic.ogre.model.Quaternion.class);
        if (dotSceneQuaternion != null) {
            Quaternion jmeQuaternion = new Quaternion();
            jmeNode.setLocalRotation(jmeQuaternion.set(XMLUtil.getFloatString(dotSceneQuaternion.getX()), XMLUtil.getFloatString(dotSceneQuaternion.getY()), XMLUtil.getFloatString(dotSceneQuaternion.getZ()), XMLUtil.getFloatString(dotSceneQuaternion.getW())));
        }

    }

    private <T> T findInList(List<?> list, Class<T> clazz) {
        for (Object o : list) {
            if (clazz.isInstance(o)) {
                return clazz.cast(o);
            }
        }
        return null;
    }
}
